#####################################################################
# File:         GroupedReport.py
# Product:      KnowledgeEngine
#
# Copyright:    Copyright (c) 2002, Faulkner Technologies.
# Author:       Darcy Clark
#
# Description:  This file defines the GroupedReport class. This
#               is a combined report designes specifically for use
#               with the MultipleChoice Question. It will only work
#               on models that have two special components added:
#               - A Grouping Identifier - a text box that prompts
#                 the assessee for an id to group by
#               - A Principal Identifier - a True/False that checks
#                 if the assessee is or represents the principal being
#                 assessed.
#
# See Also:     Component, Model, Section
#####################################################################

#####################################################################
## Knowledge Engine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.KnowledgeEngineCore import *
from Products.KnowledgeEngine.Report import Report, ReportInfo
from Products.KnowledgeEngine.Model.Model import Model
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from ImageFile import ImageFile

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## GroupedReportInfo Class Definition
class GroupedReportInfo(ReportInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """
    
    #---------------------------------------------------------------#
    
    def getClassName(self):
        """
            Returns the name of the class for which 
            we are providing information.
        """
        return 'GroupedReport'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """
    
        return "Grouped Report"
        
    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.  
        """
        
        return "reportGrouped"
        
    #---------------------------------------------------------------#
    
    def getClassIcon(self):
        """
            Return the appropriate icon file for the class.
        """
        
        return ImageFile('www/icon.gif', globals())

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):
        """
            Returns if the specified child is permitted as a 
            child of the class' instances.
            
            NOTE: This is from this class' instance perspective.
            
            For component containers, this always overrides what the
            return value from childClassInfo.isPermittedInContainer(...)
        """
        
        #DEFAULT RULE: 360ScoredReports may contain Elements as children
        return childClassInfo.isInstanceOf('Element')
    
    #---------------------------------------------------------------#

    def onConfigureProperties(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific properties using the PropertyReflection interface.
            
            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered
            
            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """

        #initialise the super-class properties for reflection
        ReportInfo.onConfigureProperties(self)
        
        #add the 'groupByID' property        
        self.addPropertyDefinition(PropertyDefinition(identity="groupByID", displayName="Group By ID", description="", defaultValue="", propertyType=pt_STRING, propertyFormat=pf_NATIVE, propertyStructure=ps_ATOMIC))        
        
    #---------------------------------------------------------------#

#####################################################################
## GroupedReport Class Definition
class GroupedReport(Report):
    """
        A class to represent a simple report that uses the components
        within the containing Model to build a report
    """

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = GroupedReportInfo()

    #---------------------------------------------------------------#

    # DTML Methods
    index_html = DTMLFile('dtml/index_html', globals())
    csv_html = DTMLFile('dtml/csv_html', globals())

    #---------------------------------------------------------------#

    def __init__(self, id, identity):
        "Constructor for the GroupedReport"        

        Report.__init__(self, id, identity)
        
    #---------------------------------------------------------------#

    def onAfterInstanciation(self):
        """
            Handle Knowledge Engine specific actions after this object 
            has been loaded into memory.  
            
            This is useful for performing backwards compatibility
        """

        #perform BooleanComponent.onAfterInstanciation processing
        Report.onAfterInstanciation(self)
                        
        ###print "DEBUG: CheckBoxComponent.onAfterInstanciation: Completed"

    #---------------------------------------------------------------#

    def getReportType(self):
        """
            Returns the type of report. Options may include
            'single' - a report designed for a single user
            'grouped' - reports designed for grouping assessments
            
            by default we return 'single'
        """

        return 'grouped'
    
    #---------------------------------------------------------------#

    def getAssessmentsByGroupId(self,groupid=None):
        """returns a list of assessments where a particular value (groupid)
           was entered into a particlar field (groupByID)
        """

        assessments=[]

        if groupid=='all':
            aids=self.getModel().getAssessmentIds()
        else:
            aids=self.getAssessmentsByValue(self.groupByID,groupid)
        for a in aids:
            assessment=self.getModel().getAssessment(a)
            if assessment.isLocked():
                assessments.append(assessment)

        return assessments

    #---------------------------------------------------------------#

    def groupedScoreDump(self, assessmentlist):
        """
            Accepts the list generated from the getAssessmentsByGroupId() method
            
            Returns a array of data for export.
            Format:
            AID:
            USER:
            STATUS:
            CID,REF,CONTENT,WEIGHTING: DATA
        """

        assessments=assessmentlist

        model=self.getModel()
        modelid=model.getIdentity()
        array=[]
            
        #First Row has Assessment IDs
        aids=[]
        aids.extend(['AID:','-','-','-'])
        for a in assessments:
            aids.append(a.getIdentity())
        array.append(aids)

        #Second Row is Users
        users=[]
        users.extend(['USER:','-','-','-'])
        for a in assessments:
            user = a.getUser()
            if user == 'unknown':
                users.append('unknown')
            else:
                users.append(user.getUserName())
        array.append(users)


        #Now itterate through the sections for assessment data
        #Note that we only want scorable components for this data.
        #For ease we will let the section class do all the work
        #That way it will work when we add new scorable components.
        for s in self.getComponentContainers():
            array.extend(s.csvScoreDump(assessments))

        return array

     #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

# Register Class Information with the Knowledge Engine
registerGenericObjectClass(GroupedReport)

#####################################################################
